import threading
import time
import random


class Timer:
    def __init__(self, update_callback, user_config, user_logger):
        """
        初始化 Timer 类的实例。

        :param update_callback: 用于更新计时显示的回调函数
        :param user_config: 用户配置信息，包含专注时长、休息时长等参数
        :param user_logger: 日志记录器实例，用于记录操作日志
        """
        self.config = user_config
        self.logger = user_logger
        self.reminder_callback = None
        self.completion_callback = None
        self.update_callback = update_callback
        self.focus_duration = self.config.get('focus_duration', 90) * 60  # 转换为秒
        self.break_duration = self.config.get('break_duration', 20) * 60
        self.current_time = self.focus_duration
        self.running = False
        self.paused = False
        self.timer_thread = None
        self.current_mode = 'focus'
        self.round_count = 0
        self.reminder_interval = None
        self.next_reminder = None
        # 测试
        self.speed_factor = self.config.get('speed_factor', 1)  # 加速因子，默认为1

    def start(self):
        """
        启动或恢复计时器。若计时器未运行，则创建新线程启动计时；若计时器已暂停，则恢复计时。
        """
        if not self.running:
            self.running = True
            self.paused = False
            self.timer_thread = threading.Thread(target=self._run, daemon=True)
            self.timer_thread.start()
        elif self.paused:
            self.paused = False
        self.logger.info('Timer started in {} mode'.format(self.current_mode))

    def pause(self):
        """
        切换计时器的暂停状态。若计时器正在运行，则切换其暂停状态，并记录日志。
        """
        if self.running:
            self.paused = not self.paused
            status = 'paused' if self.paused else 'resumed'
            self.logger.info('Timer {} in {} mode'.format(status, self.current_mode))

    def reset(self):
        """
        重置计时器。停止计时，将当前时间重置为当前模式的初始时长，并更新显示。
        """
        self.running = False
        self.current_time = self.focus_duration if self.current_mode == 'focus' else self.break_duration
        self.update_callback(0, 0, 0)
        self.logger.info('Timer reset')

    def switch_mode(self, mode):
        """
        切换计时器模式（专注或休息），并重置当前时间为对应模式的初始时长。

        :param mode: 要切换到的模式，'focus' 表示专注模式，其他表示休息模式
        """
        self.current_mode = mode
        if mode == 'focus':
            self.current_time = self.config.get('focus_duration', 90) * 60
        else:
            self.current_time = self.config.get('break_duration', 20) * 60
        hours, remainder = divmod(self.current_time, 3600)
        minutes, seconds = divmod(remainder, 60)
        self.update_callback(hours, minutes, seconds)
        self.logger.info('Switched to {} mode'.format(mode))

    def _run(self):
        """
        计时器的核心运行逻辑，在单独的线程中执行。负责更新计时显示、检查计时结束和随机提醒。
        """
        while self.running:
            if not self.paused:
                # 更新倒计时
                hours, remainder = divmod(self.current_time, 3600)
                minutes, seconds = divmod(remainder, 60)
                self.update_callback(hours, minutes, seconds)

                # 检查是否计时结束
                if self.current_time <= 0:
                    self._handle_completion()

                # 检查随机提醒
                if self.current_mode == 'focus' and self._should_trigger_reminder():
                    self._trigger_reminder()

                time.sleep(1 / self.speed_factor)
                self.current_time -= int(self.speed_factor)
            else:
                time.sleep(0.1 / self.speed_factor)

    def _handle_completion(self):
        """
        处理计时结束事件。根据当前模式切换到另一种模式，增加轮次计数，并触发完成提醒。
        """
        if self.current_mode == 'focus':
            # 专注结束，切换到休息模式
            self.round_count += 1
            self.logger.info('Focus session completed (Round {})'.format(self.round_count))
            self.switch_mode('break')
            # 触发完成提醒
            self._trigger_completion_alert()
            self.start()
        else:
            # 休息结束，切换到专注模式
            self.switch_mode('focus')
            self.logger.info('Break session completed')
            # 触发完成提醒，传入正确的模式
            self._trigger_completion_alert()
            self.start()

    def _should_trigger_reminder(self):
        """
        判断是否应该触发随机提醒。若未初始化提醒间隔，则进行初始化；若当前时间达到提醒时间，则返回 True。
        """
        # 初始化随机提醒间隔
        if self.reminder_interval is None:
            min_interval = self.config.get('min_interval', 10) * 60
            max_interval = self.config.get('max_interval', 15) * 60
            self.reminder_interval = random.randint(min_interval, max_interval)
            self.next_reminder = time.time() + self.reminder_interval

        return time.time() >= self.next_reminder

    def _trigger_reminder(self):
        """
        触发随机提醒，调用提醒回调函数，并设置下一次提醒时间。
        """
        # 触发随机提醒
        self.logger.info('Random reminder triggered')
        # 这里应该调用通知系统
        if hasattr(self, 'reminder_callback'):
            self.reminder_callback()

        # 设置下一次提醒
        min_interval = self.config.get('min_interval', 10) * 60
        max_interval = self.config.get('max_interval', 15) * 60
        self.reminder_interval = random.randint(min_interval, max_interval)
        self.next_reminder = time.time() + self.reminder_interval

    def _trigger_completion_alert(self):
        """
        触发计时完成提醒，调用完成回调函数和提醒回调函数。
        """
        # 触发完成提醒
        if hasattr(self, 'completion_callback'):
            self.completion_callback(self.current_mode)
        if hasattr(self, 'reminder_callback'):
            self.reminder_callback()

    def set_reminder_callback(self, callback):
        """
        设置提醒回调函数。

        :param callback: 提醒回调函数
        """
        self.reminder_callback = callback

    def set_completion_callback(self, callback):
        """
        设置完成回调函数。

        :param callback: 完成回调函数
        """
        self.completion_callback = callback

    def get_current_mode(self):
        """
        获取当前计时器模式。

        :return: 当前模式，'focus' 或 'break'
        """
        return self.current_mode

    def get_round_count(self):
        """
        获取当前专注轮次。

        :return: 当前专注轮次
        """
        return self.round_count

    def get_time_remaining(self):
        """
        获取当前剩余时间。

        :return: 当前剩余时间（秒）
        """
        return self.current_time

    def set_time_remaining(self, seconds):
        """
        设置当前剩余时间。

        :param seconds: 要设置的剩余时间（秒）
        """
        self.current_time = seconds

    def is_running(self):
        """
        判断计时器是否正在运行。

        :return: 若计时器正在运行，返回 True；否则返回 False
        """
        return self.running

    def is_paused(self):
        """
        判断计时器是否处于暂停状态。

        :return: 若计时器处于暂停状态，返回 True；否则返回 False
        """
        return self.paused


if __name__ == '__main__':
    # 测试代码
    import logging

    logging.basicConfig(level=logging.INFO)
    logger = logging.getLogger(__name__)


    def update_display(hours, minutes, seconds):
        print(f'Time remaining: {hours:02d}:{minutes:02d}:{seconds:02d}')


    config = {
        'focus_duration': 90,
        'break_duration': 20,
        'min_interval': 10,
        'max_interval': 15
    }

    timer = Timer(update_display, config, logger)
    timer.start()
